package com.dhh.sky.activity;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.FloatMath;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.MenuItem.OnMenuItemClickListener;
import com.devspark.appmsg.AppMsg;
import com.dhh.sky.R;
import com.dhh.sky.SDAApplication;
import com.dhh.sky.model.SkyDrivePhoto;
import com.dhh.sky.service.DownloadOperationService;
import com.dhh.sky.util.CUtil;
import com.dhh.sky.util.Constant;
import com.dhh.sky.util.FileManager;
import com.dhh.sky.util.JsonKeys;
import com.dhh.sky.util.OperationManager;
import com.microsoft.live.LiveConnectClient;
import com.microsoft.live.LiveDownloadOperation;
import com.microsoft.live.LiveDownloadOperationListener;
import com.microsoft.live.LiveOperation;
import com.microsoft.live.LiveOperationException;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.assist.ImageLoadingListener;

public class ImagePagerActivity extends SherlockFragmentActivity {
	private Context context;
    private DisplayImageOptions options;
    private ImageLoader imageLoader = ImageLoader.getInstance();
    private ViewPager pager;
	private boolean isHideBar = false;
	private LinearLayout actionBarBottom;
	private LinearLayout actionBarUp;
	private TextView title;
	private Timer timer;
    private String path;
    private String initId;
	private int pagerPosition = 0;
	private FileManager fm;
	private OperationManager om;
	private ProgressDialog progress;
	private List<SkyDrivePhoto> photos = new ArrayList<SkyDrivePhoto>();	
	
	// These matrices will be used to move and zoom image
	Matrix matrix = new Matrix();
	Matrix savedMatrix = new Matrix();

	// We can be in one of these 3 states
	static final int NONE = 0;
	static final int DRAG = 1;
	static final int ZOOM = 2;
	int mode = NONE;

	// Remember some things for zooming
	PointF start = new PointF();
	PointF mid = new PointF();
	float oldDist = 1f;
	String savedItemClicked;
	
    public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.img_pager);
            Bundle bundle = getIntent().getExtras();   
            fm = new FileManager(this);
            om = new OperationManager(this);
            context = this;
            
            path = bundle.getString(Constant.PARAM_PATH);
            initId = bundle.getString(Constant.PARAM_ID);

    		actionBarBottom = (LinearLayout) this.findViewById(R.id.actionBarBottom);
    		actionBarUp = (LinearLayout) this.findViewById(R.id.actionBarUp);
    		title = (TextView) this.findViewById(R.id.ip_title);
            loadImages(path);            
            imageLoader.init(ImageLoaderConfiguration.createDefault(this));            
            options = new DisplayImageOptions.Builder()
	            .showStubImage(R.drawable.image_picker_placeholder)
	            .cacheInMemory()
	            .cacheOnDisc()
	            .build();

            pager = (ViewPager) findViewById(R.id.pager);
            pager.setOnPageChangeListener(new OnPageChangeListener(){
                    @Override
                    public void onPageScrollStateChanged(int arg0) {}

                    @Override
                    public void onPageSelected(int position) {
                        pagerPosition = position;
                        initId = photos.get(pagerPosition).getId();
                        getSupportActionBar().setTitle(photos.get(position).getName());
    					Log.d(Constant.TAG, pagerPosition+":"+photos.get(pagerPosition).getId());		
                }

                    @Override
                    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
             });
            pager.setAdapter(new ImagePagerAdapter(photos));
            pager.setCurrentItem(pagerPosition);
            getSupportActionBar().hide();
            
            ImageButton delete = (ImageButton) this.findViewById(R.id.pii_delete);
            delete.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
		            showDialog(0);
				}
			});
            
            ImageButton download = (ImageButton) this.findViewById(R.id.pii_download);
            download.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					om.addDownloadOperation(new String[]{initId}, path);
		            Intent intent = new Intent(context,DownloadOperationService.class);
		            startService(intent);
				}
			});
            
            ImageButton link = (ImageButton) this.findViewById(R.id.pii_link);
            link.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					showDialog(1);
				}
			});
            
            ImageButton share = (ImageButton) this.findViewById(R.id.pii_share);
            share.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					ShareTask share = new ShareTask();
					share.execute(initId);
				}
			});
    }

    @Override
    protected void onStop() {
            imageLoader.stop();
            super.onStop();
    }
    
    @Override
    protected void onResume() {
            super.onResume();
            this.hideBar(false);
    }
    
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event){
		if(keyCode == KeyEvent.KEYCODE_BACK){
			if(progress!=null){
				progress.dismiss();
				progress = null;
				return true;
			}
		}
		
		return super.onKeyDown(keyCode, event);
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    	MenuItem delete = menu.add(getString(R.string.ab_delete));
    	delete.setIcon(R.drawable.ic_delete);
    	delete.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
    	delete.setOnMenuItemClickListener(new OnMenuItemClickListener(){
			@Override
			public boolean onMenuItemClick(MenuItem item) {			
				return true;
			}});
    	
    	MenuItem downlaod = menu.add(getString(R.string.ab_download));
    	downlaod.setIcon(R.drawable.ic_download);
    	downlaod.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
    	downlaod.setOnMenuItemClickListener(new OnMenuItemClickListener(){
			@Override
			public boolean onMenuItemClick(MenuItem item) {			
				return true;
			}});
    	return true;
    }
    
    private void loadImages(String path){
    	photos = fm.getPhotos(path);
    	for(int i=0; i<photos.size(); i++){
    		if(photos.get(i).getId().equals(initId)){
    			pagerPosition = i;
    			break;
    		}
    	}
    }
    
    class HideBarTask extends TimerTask {
		@Override
		public void run() {
			Message msg = new Message();
			Bundle data = new Bundle();
			data.putBoolean("isHid", true);
			msg.setData(data);
			hidHandler.sendMessage(msg);
		}
	}
	
	private Handler hidHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {    
    		Bundle data = msg.getData();
    		boolean isHid = data.getBoolean("isHid");
    		hideBar(isHid);
        }
    };
    
    private void hideBar(boolean isHid){
		isHideBar = isHid;
		if(isHideBar){
			actionBarBottom.setVisibility(View.GONE);
			actionBarUp.setVisibility(View.GONE);
			if(timer!=null){
				timer.cancel();
				timer.purge();
			}
		}else{
			actionBarBottom.setVisibility(View.VISIBLE);
			actionBarUp.setVisibility(View.VISIBLE);
			timer = new Timer();
			timer.schedule(new HideBarTask(), 5000);
		}
	}
    
    @Override
    protected Dialog onCreateDialog(final int id) {
		Dialog dialog = null;
		 switch (id) {
         	case 0: {
         		AlertDialog.Builder builder = new AlertDialog.Builder(this);
         		builder.setTitle(context.getString(R.string.title_delete_image));
         		builder.setMessage(context.getString(R.string.msg_delete_image_confirm));
         		builder.setPositiveButton(context.getString(R.string.label_ok), 
         				new OnClickListener() {
			            	@Override
			            	public void onClick(DialogInterface dialog, int which) {
			            		DeleteTask task = new DeleteTask();
					            task.execute(initId);
			            	}
         				});
         		builder.setNegativeButton(context.getString(R.string.label_cancel), 
         				new OnClickListener() {
				             @Override
				             public void onClick(DialogInterface dialog, int which) {
				                dialog.cancel();
				             }
         				});
         		dialog = builder.create();
         	}
         	
         	case 1:{
         		AlertDialog.Builder builder=new android.app.AlertDialog.Builder(this);
         		builder.setTitle("Link");
         		builder.setSingleChoiceItems(R.array.link_type, 0, new OnClickListener(){
                    public void onClick(DialogInterface dialog, int which) {
                    }
                });         		
         		builder.setPositiveButton(context.getString(R.string.label_ok), new DialogInterface.OnClickListener(){
                    public void onClick(DialogInterface dialog, int which){
                    	LinkTask link = new LinkTask();
                    	String type = which==1 ?"shared_read_link":"shared_edit_link";
                    	link.execute(new String[]{initId,type});
                    }
                });
         		builder.setNegativeButton(context.getString(R.string.label_cancel), new DialogInterface.OnClickListener(){
                    public void onClick(DialogInterface dialog, int which){
                    	dialog.dismiss();
                    }
                });
         		dialog = builder.create();
         	}
         }
		return dialog;
	}

    private class ImagePagerAdapter extends PagerAdapter {
            private List<SkyDrivePhoto> photos;
            private LayoutInflater inflater;

            ImagePagerAdapter(List<SkyDrivePhoto> photos) {
                    this.photos = photos;
                    inflater = getLayoutInflater();
            }

            @Override
            public void destroyItem(View container, int position, Object object) {
                    ((ViewPager) container).removeView((View) object);
            }

            @Override
            public void finishUpdate(View container) {
            }

            @Override
            public int getCount() {
                    return photos.size();
            }

            @Override
            public Object instantiateItem(View view, int position) {
                    final FrameLayout imageLayout = (FrameLayout) inflater.inflate(R.layout.item_pager_image, null);
                    final ImageView imageView = (ImageView) imageLayout.findViewById(R.id.pi_image);
                    final ProgressBar spinner = (ProgressBar) imageLayout.findViewById(R.id.pi_loading);
                    imageView.setOnClickListener(new View.OnClickListener() {						
						@Override
						public void onClick(View v) {
							hideBar(!isHideBar);					
						}
					});
                    title.setText(photos.get(position).getName());
                    String src = (photos.get(position).getImages())[0].getSource();
                    if(CUtil.isFileExists(photos.get(position))){
                    	src = "file:///"+Constant.SKYDRIVE_LOCAL_PATH+"/"+CUtil.buildFileName(photos.get(position));
                    }
                    imageLoader.displayImage(src, imageView, options, new ImageLoadingListener() {
                        @Override
                        public void onLoadingStarted() {
                                spinner.setVisibility(View.VISIBLE);
                        }

                        @Override
                        public void onLoadingFailed(FailReason failReason) {
                                Toast.makeText(ImagePagerActivity.this, "Failed to load image!", Toast.LENGTH_SHORT).show();
                                spinner.setVisibility(View.GONE);
                                imageView.setImageResource(android.R.drawable.ic_delete);
                        }

                        @Override
                        public void onLoadingCancelled() {
                        	Toast.makeText(ImagePagerActivity.this, "Image load cancelled!", Toast.LENGTH_SHORT).show();
                            spinner.setVisibility(View.GONE);
                            imageView.setImageResource(android.R.drawable.ic_delete);
                        }

						@Override
						public void onLoadingComplete(Bitmap bitmap) {
                            spinner.setVisibility(View.GONE);
							
						}
                    });

                    ((ViewPager) view).addView(imageLayout, 0);
                    return imageLayout;
            }

            @Override
            public boolean isViewFromObject(View view, Object object) {
                    return view.equals(object);
            }

            @Override
            public void restoreState(Parcelable state, ClassLoader loader) {
            }

            @Override
            public Parcelable saveState() {
                    return null;
            }

            @Override
            public void startUpdate(View container) {
            }
    }
    
    public boolean onTouch(View v, MotionEvent event) {
        // TODO Auto-generated method stub

        ImageView view = (ImageView) v;
        dumpEvent(event);

        // Handle touch events here...
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
            savedMatrix.set(matrix);
            start.set(event.getX(), event.getY());
            mode = DRAG;
            break;
        case MotionEvent.ACTION_POINTER_DOWN:
            oldDist = spacing(event);
            if (oldDist > 10f) {
                savedMatrix.set(matrix);
                midPoint(mid, event);
                mode = ZOOM;
            }
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_POINTER_UP:
            mode = NONE;
            break;
        case MotionEvent.ACTION_MOVE:
            if (mode == DRAG) {
                matrix.set(savedMatrix);
                matrix.postTranslate(event.getX() - start.x, event.getY()
                        - start.y);
            } else if (mode == ZOOM) {
                float newDist = spacing(event);
                if (newDist > 10f) {
                    matrix.set(savedMatrix);
                    float scale = newDist / oldDist;
                    matrix.postScale(scale, scale, mid.x, mid.y);
                }
            }
            break;
        }

        view.setImageMatrix(matrix);
        return true;
    }
    
    private void dumpEvent(MotionEvent event) {
        String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE",
                "POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" };
        StringBuilder sb = new StringBuilder();
        int action = event.getAction();
        int actionCode = action & MotionEvent.ACTION_MASK;
        sb.append("event ACTION_").append(names[actionCode]);
        if (actionCode == MotionEvent.ACTION_POINTER_DOWN
                || actionCode == MotionEvent.ACTION_POINTER_UP) {
            sb.append("(pid ").append(
                    action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
            sb.append(")");
        }
        sb.append("[");
        for (int i = 0; i < event.getPointerCount(); i++) {
            sb.append("#").append(i);
            sb.append("(pid ").append(event.getPointerId(i));
            sb.append(")=").append((int) event.getX(i));
            sb.append(",").append((int) event.getY(i));
            if (i + 1 < event.getPointerCount())
                sb.append(";");
        }
        sb.append("]");
    }

    /** Determine the space between the first two fingers */
    private float spacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return FloatMath.sqrt(x * x + y * y);
    }

    /** Calculate the mid point of the first two fingers */
    private void midPoint(PointF point, MotionEvent event) {
        float x = event.getX(0) + event.getX(1);
        float y = event.getY(0) + event.getY(1);
        point.set(x / 2, y / 2);
    }
    
    class DeleteTask  extends AsyncTask<String, Void, Boolean> {
    	private ProgressDialog progress;
    	private String id;
    	
    	protected void onPreExecute() {
    		progress = new ProgressDialog(ImagePagerActivity.this);
            progress.setMessage("Deleting the image...");
            progress.show();
        }

		@Override
		protected Boolean doInBackground(String... ids) {
			Boolean flag = false;
			this.id = ids[0];
			try{
				if(CUtil.isNetworkAvailable(ImagePagerActivity.this)){
					LiveConnectClient client = ((SDAApplication) getApplication()).getConnectClient();
					if(client!=null){
						LiveOperation operation = client.delete(ids[0]);
						flag = !operation.getResult().has(JsonKeys.ERROR);
					}
				}
			}catch(Exception e){
				Log.e(Constant.TAG, e.getMessage(),e);
			}
            
			return flag;
		}
		
		@Override
	    protected void onPostExecute(final Boolean success) {
			progress.dismiss();
			if(success){
				Message msg = CUtil.buildMessage();
				msg.getData().putString(Constant.PARAM_ID, id);
				deleteHandler.sendMessage(msg);
			}else{
				showToast("Failed to delete the image!",true);
			}
		}
    	
    }
    
    class LinkTask  extends AsyncTask<String, Void, Boolean> {
    	private ProgressDialog progress;
    	private String id;
    	private String type;
    	private String link;
    	
    	protected void onPreExecute() {
    		progress = new ProgressDialog(ImagePagerActivity.this);
    		//TODO replace from resource
            progress.setMessage("Getting the link...");
            progress.show();
        }

		@Override
		protected Boolean doInBackground(String... args) {
			Boolean flag = false;
			this.id = args[0];
			this.type = args[1];
			
			
			try{
				if(CUtil.isNetworkAvailable(ImagePagerActivity.this)){
					LiveConnectClient client = ((SDAApplication) getApplication()).getConnectClient();
					if(client!=null){
						LiveOperation operation = client.get(id+"/"+type);
						flag = !operation.getResult().has(JsonKeys.ERROR);
						link = operation.getResult().optString("link");
					}
				}
			}catch(Exception e){
				Log.e(Constant.TAG, e.getMessage(),e);
			}
            
			return flag;
		}
		
		@Override
	    protected void onPostExecute(final Boolean success) {
			progress.dismiss();
			if(success){
				Message msg = CUtil.buildMessage();
				msg.getData().putString(Constant.PARAM_PATH, link);
				linkHandler.sendMessage(msg);
			}else{
				showToast("Failed to get link!",true);
			}
		}
    	
    }
    
    class ShareTask  extends AsyncTask<String, Void, Boolean> {
    	private final ProgressDialog progress = new ProgressDialog(ImagePagerActivity.this);
    	private String id;
    	private String name;
    	
    	protected void onPreExecute() {
    		//TODO replace from resource
            progress.setMessage("Downloading the file...");
            progress.show();
        }

		@Override
		protected Boolean doInBackground(String... args) {
			Boolean flag = false;
			this.id = args[0];			
			name = fm.getFile(id).getName();
			
			try{
				if(CUtil.isNetworkAvailable(ImagePagerActivity.this)){ 
					LiveConnectClient client = ((SDAApplication) getApplication()).getConnectClient();
					if(client!=null){
						String dir = Environment.getExternalStorageDirectory().getPath();
						File director = new File(dir+"/SkyDrive");
						if(!director.exists()) director.mkdir();										
						File file = new File(dir+"/SkyDrive/"+name);
						if(file.exists()){
							file.delete();
							file.createNewFile();
						}
						client.downloadAsync(id, file, new LiveDownloadOperationListener(){
							@Override
							public void onDownloadCompleted(LiveDownloadOperation operation) {	
								progress.dismiss();
								Message msg = CUtil.buildMessage();
								msg.getData().putBoolean(Constant.PARAM_DONE, true);
								msg.getData().putString(Constant.PARAM_PATH, name);
								shareHandler.sendMessage(msg);
							}

							@Override
							public void onDownloadFailed(LiveOperationException exception,LiveDownloadOperation operation) {
								progress.dismiss();
								Message msg = CUtil.buildMessage();
								msg.getData().putBoolean(Constant.PARAM_DONE, false);
								shareHandler.sendMessage(msg);
							}

							@Override
							public void onDownloadProgress(int totalBytes,int bytesRemaining,LiveDownloadOperation operation) {
								
							}
						});
					}
				}
			}catch(Exception e){
				Log.e(Constant.TAG, e.getMessage(),e);
			}
            
			return flag;
		}
		
		@Override
	    protected void onPostExecute(final Boolean success) {
		}
    	
    }
    
    private Handler deleteHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {   
        	String id = msg.getData().getString(Constant.PARAM_ID);
        	int position = 0;
        	for(int i=0; i<photos.size(); i++){
        		if(photos.get(i).getId().equals(id)){
        			position = i;
        			break;
        		}
        	}
        	
        	if(pagerPosition==position){
        		photos.remove(pagerPosition);
    			pager.setAdapter(new ImagePagerAdapter(photos));
    			if(photos.size()>0){
    				if(pagerPosition>=(photos.size()-1)){
    					pager.setCurrentItem(photos.size()-1);
    				}else{
    					pager.setCurrentItem(pagerPosition);
    				}
    			}else{
    				//TODO show no images.
    			}
        	}else{
        		photos.remove(position);
        		pager.getAdapter().notifyDataSetChanged();
        	}
        	
        	initId = photos.get(pagerPosition).getId();
        }
    }; 
    
    private Handler linkHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {   
        	String link = msg.getData().getString(Constant.PARAM_PATH);
			Intent sendIntent = new Intent();
			sendIntent.setAction(Intent.ACTION_SEND);
			sendIntent.putExtra(Intent.EXTRA_TEXT, link);
			sendIntent.setType("text/plain");
			startActivity(sendIntent);
        }
    }; 
    
    private Handler shareHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {   
        	Boolean succes = msg.getData().getBoolean(Constant.PARAM_DONE);
        	if(succes){
            	String name = msg.getData().getString(Constant.PARAM_PATH);
    			Intent sendIntent = new Intent();
    			sendIntent.setAction(Intent.ACTION_SEND);
    			sendIntent.setType("*/*");
    			sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(Environment.getExternalStorageDirectory().getPath()+"/SkyDrive/"+name)));
    			startActivity(sendIntent);
        	}else{
        		showToast("Failed to share the file!",true);
        	}
        }
    }; 
    
    public void showToast(String message,boolean isAlert){
		 AppMsg.Style style = AppMsg.STYLE_INFO;
		 if(isAlert){
			 style = AppMsg.STYLE_ALERT;
		 }
		AppMsg appMsg = AppMsg.makeText(this, message, style);
		appMsg.setLayoutGravity(Gravity.BOTTOM);
		appMsg.show();
	}
}
